package com.xrui.craft.lexer;

import java.util.HashMap;
import java.util.Map;

public class Tokener {
    private enum DfaState {
        Initial,
        Id,
        Plus,
        LeftParen,
        RightParen,
        Comma
    }

    private static final Map<String,Integer> keywords = new HashMap<String,Integer>();
    static{
        keywords.put("random",Integer.valueOf(1));
    }
    private final class SimpleToken implements Token {

        private TokenType type = null;


        private String text = null;


        @Override
        public TokenType getType() {
            return type;
        }

        @Override
        public String getText() {
            return text;
        }
    }

    private String expr;
    private int pos,len;
    private DfaState state;
    private SimpleToken token;
    private StringBuilder tokenValue;
    public Tokener(String expr){
        this.expr = expr;
        this.len =  expr.length();
        pos = 0;
        state = DfaState.Initial;
        tokenValue = null ;
        token = null;
    }

    public Token getToken(){

        if(pos >= len){
            token.type = TokenType.EOD;
            return token;
        }
        state      =  DfaState.Initial;
        token      =  new SimpleToken();
        tokenValue =  new StringBuilder();
        while (pos < len) {
            int codePoint  = expr.codePointAt(pos);
            char character = expr.charAt(pos);

            switch (state) {
                case Initial:
                    initToken();
                    break;
                case Id:
                    if (Character.isAlphabetic(codePoint)){
                        tokenValue.append(character);
                    } else {
                        token.text = tokenValue.toString();
                        if (keywords.containsKey(token.text)){
                            token.type = TokenType.RANDOM;
                        }
                        return token;
                    }
                    break;

                case Comma:
                case Plus:
                case LeftParen:
                case RightParen:
                    token.text = tokenValue.toString();
                    return token;
                default:
            }

            pos++;
        }
        return token;
    }

    private void initToken(){
        int codePoint  = expr.codePointAt(pos);
        char character = expr.charAt(pos);
        if (Character.isAlphabetic(codePoint)) {
            state = DfaState.Id;
            token.type = TokenType.ID;

        }else if( character == '('){
            token.type = TokenType.LP;
            state = DfaState.LeftParen;
        }
        else if( character == ')'){
            token.type = TokenType.RP;
            state = DfaState.LeftParen;
        }else if(character == '+'){
            token.type = TokenType.PLUS;
            state = DfaState.Plus;
        }else if(character == ','){
            token.type = TokenType.COMMA;
            state = DfaState.Comma;
        }
        tokenValue.append(expr.charAt(pos));
    }

    public static void main(String args[]){
        Tokener tokener = new Tokener("aaa+random()");
        Token token = tokener.getToken();
        while (token.getType() != TokenType.EOD){
           switch(token.getType()){
               case ID:
                   System.out.println(token.getText());

                   break;
               case RANDOM:
                   System.out.println("Random function :" + token.getText());

                   break;
               case  LP:
                   System.out.println("it is LeftParen");
                   break;
               case RP:
                   System.out.println("it is RightParen");
                   break;
               case PLUS:
                   System.out.println("it is Plus");
                   break;
               default:
                   System.out.println("unknown token");
           }
            token = tokener.getToken();
        }
    }
}
